﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using YAPSAR.Domain;
using YAPSAR.Database;
using NHibernate;
using NHibernate.Criterion;

namespace YAPSAR.Analyzation
{
    public class WorkUnitAnalyzer
    {
        private static WorkUnitAnalyzer static_instance;
        public static WorkUnitAnalyzer Instance
        {
            get
            {
                if (static_instance == null)
                {
                    static_instance = new WorkUnitAnalyzer();
                }

                return static_instance;
            }
        }

        private WorkUnitAnalyzer()
        {
        }

        /// <summary>
        /// Get the project from the information available in the work unit.
        /// </summary>
        /// <param name="workUnit"></param>
        /// <returns>The possible Project</returns>
        public Project GetProject(Process a)
        {
            // TODO: Find the project. Based on tags?
            return null;
        }

        /// <summary>
        /// Get the type of the work unit from the information available.
        /// </summary>
        /// <param name="workUnit"></param>
        /// <returns></returns>
        public WorkType GetType(Process a)
        {
            return null;
        }

        public IList<ProcessTag> GetProcessTags(Process p)
        {
            // TODO: Find the tags
            return new List<ProcessTag>();
        }

        public IList<ProcessTag> GetProcessInstanceTags(ProcessInstance pi)
        {
            // TODO: Find the tags
            return new List<ProcessTag>();
        }

        public ProcessInstance GetProcessInstance(WorkUnit workUnit, String windowTitle, String executablePath, int processId)
        {
            var processCriteria = DatabaseManager.Instance.Session.CreateCriteria<Process>();
            processCriteria.Add(Restrictions.Eq("ExecutableFilePath", executablePath));

            Process process = null;
            foreach (var p in processCriteria.Future<Process>())
            {
                // We found a matching process, so we will use that.
                process = p;
                break;
            }

            ProcessInstance processInstance = null;
            if (process == null)
            {
                // We could not find a matching process, so we will have to create one.
                process = new Process();
                process.ExecutableFilePath = executablePath;
                process.Tags = this.GetProcessTags(process);
                process.Project = this.GetProject(process);
            }
            else
            {
                // We found a process, so we can search for a process instance of the process.
                var processInstanceCriteria = DatabaseManager.Instance.Session.CreateCriteria<ProcessInstance>();
                processInstanceCriteria.CreateAlias("Process", "p");
                processInstanceCriteria.Add(Restrictions.Eq("p.Id", process.Id));
                processInstanceCriteria.Add(Restrictions.Eq("WindowTitle", windowTitle));

                foreach (var pi in processInstanceCriteria.Future<ProcessInstance>())
                {
                    // We found a matching process instance, so we will use that.
                    processInstance = pi;
                    break;
                }
            }

            if (processInstance == null)
            {
                // We could not find a matching process instance, so we will have to create a new one
                processInstance = new ProcessInstance();
                processInstance.Process = process;
                processInstance.WindowTitle = windowTitle;
                processInstance.Tags = this.GetProcessInstanceTags(processInstance);

                // Add the new instance to the process.
                process.Instances.Add(processInstance);
            }

            return processInstance;
        }
    }
}
